import {BaseCodeGenerator} from "../BaseCodeGenerater";
import path = require("path");
import * as fs from "fs";
import {ConfigDataEntity} from "../../../generate/entitas";
import assert = require("assert");
import excelConfig from "../../../ExcelConfig";
var ejs = require("ejs");
let BaseConvert = {
	'int':   "int32",
	'long' :  'int64',
	'float':  "float",
	'string':  "string",
	'bool': "bool",
}

let typeConvert = new Map()
typeConvert.set(/list<(?<type1>[^<>]*)>/, ['repeated ${type1}', false])
typeConvert.set(/map<(?<type1>[^<>]*),(?<type2>[^<>]*)>/, ['map<${type1},${type2}>', true])
typeConvert.set(/list<list<(?<type1>[^<>]*)>>/, ['repeated List${Type1}', false],)
typeConvert.set(/map<(?<type1>[^<>]*),list<(?<type2>[^<>]*)>>/, ['Protocols.Struct.Map${Type1}List${Type2}',false])
__dirname = __dirname.replace("/dist/", "/src/")

class TypeData{
	bFind = false
	type = null
	base = false
}

export class ProtoDescGenerate extends BaseCodeGenerator{
	constructor() {
		super()
		this.dirPath = __dirname
		this.init()
		this.outPath = excelConfig.tempProjectRoot + this.className + "PB_Desc"
	}

	onBeforeGenCode() {
		this.genCustomStructProto()
	}

	onStartGeCode(entity: ConfigDataEntity) {
		this.genPBFile(entity)
	}

	convertType(mType : string) : TypeData{
		let ret = new TypeData()
		ret.base = true
		ret.bFind = false
		ret.type = null
		if (BaseConvert[mType] != undefined){
			ret.bFind = true
			ret.type = BaseConvert[mType]
			return ret
		}


		for (var [re, value] of typeConvert) {
			let mathRet : any = re.exec(mType)
			if (mathRet != null && mathRet.groups != undefined){
				ret.bFind = true
				ret.type = value[0]
				ret.base = value[1]
				if (mathRet.groups['type1'] != null){
					let s = BaseConvert[mathRet.groups.type1]
					ret.type= ret.type.replace("${type1}", s)
					s = s[0].toUpperCase() + s.substring(1,s.length)
					ret.type = ret.type.replace("${Type1}", s)
				}
				if (mathRet.groups['type2'] != null){
					let s = BaseConvert[mathRet.groups.type1]
					ret.type = ret.type.replace("${type2}", s)
					s = s[0].toUpperCase() + s.substring(1,s.length)
					ret.type = ret.type.replace("${Type2}", s)
				}
			}
		}


		return ret

	}

	genPBFile( entity : ConfigDataEntity)
	{
		let pbType = []
		let pbMemName = []
		let importStr = ""
		let columnDataList = entity.columnEntityList.value
		columnDataList.forEach(((value, index) => {
			let headData = value.memberHeadData.value
			let mType = headData.normalType
			let ret = this.convertType(mType)
			let fileName = entity.sheetName.value
			if (ret.bFind){
				pbType.push(ret.type)
			}
			if (!ret.base){
				importStr = 'import "Struct.proto";'
			}
			pbMemName.push(headData.name)

			let data = fs.readFileSync(this.makoPath + "/mako_pb_desc_generate.ejs", "utf-8")
			let retstr : string = ejs.render(data, {TableName : fileName, ValueTypeList : pbType, ValueNameList : pbMemName, ImportString : importStr})
			retstr = retstr.replace(/&#34;/g, '"').replace(/&lt;/g, "<").replace(/&gt;/g, ">")
			let clientScriptFileName = path.join(this.outPath, fileName) + ".proto"
			assert (ret.bFind, `pb gencode must be baseType, file: ${fileName}, type: ${mType}, column: ${index}"`)
			utils.writeFileSync(clientScriptFileName, retstr)
		}))
	}

	genCustomStructProto() {
		let cStructPb = path.join(this.outPath, "Struct.proto")
		utils.writeFileSync(cStructPb, `
syntax = "proto3";
package Config;

message ListInt32
{
    repeated int32 val = 1;
}

message ListLong
{
    repeated int64 val = 1;
}

message ListFloat
{
    repeated float val = 1;
}

message ListString
{
    repeated string val = 1;
}`)
	}


}